perm filename GRAFIX.HPM[UP,DOC] blob sn#543714 filedate 1981-10-10 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00008 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	Guide to graphics routines on [GRA,HPM], for Data Disc dislays.
C00010 00003	GRAPHICS TUTORIAL
C00014 00004		Procedures in this group also affect only the DD buffer, but rather
C00018 00005	Here's a sample program using most of the tools described above.
C00021 00006
C00025 00007	GOD routines
C00031 00008	TYPHDR routines
C00035 ENDMK
C⊗;
Guide to graphics routines on [GRA,HPM], for Data Disc dislays.

        to use:   REQUIRE "DDHDR.SAI[GRA,HPM]" SOURCE_FILE;
	uses:     DDFAI.REL[GRA],DDSAI.REL[GRA]

	provides: DDINIT;			initialize the DD buffer;
		  SCREEN(REAL XLO,YLO,XHI,YHI);	declare the full screen dimensions;
		  SCREEM(REAL XLO,YLO,XHI,YHI);	returns the full screen dimensions;

		  DRKEN;		cause subsequent outputs to be dark;
		  LITEN;		cause them to be light;
		  INVEN;		cause them to invert the state of things;

*+		  DOT(X,Y,THICK(0));		display a point at X,Y;
*+		  LINE(X1,Y1,X2,Y2,THICK(0));	display a line;
		  RECTAN(X1,Y1,X2,Y2);	fill in rectangle;
		  ELLIPS(X1,Y1,X2,Y2);	fill ellipse bounded by X1,Y1,X2,Y2;
		  POLYGO(N,X[1:N],Y[1:N]); fill in a polygon (concave and star ok);

		  TXTPOS(X,Y,XS,YS,DXS(0),DYS(0)); Postion text start at X,Y,
                          with general linear transf. First char's corners will be
                          (X,Y), (X+DXS,Y+YS), (X+XS+DXS,Y+YS+DYS), (X+XS,Y+DYS).
                          Text can thus be rotated, italicized and reflected.
		  TEXT(STRING);		vector text, positioned by previous TXTPOS
-		  TEXTD(STRING);	dot char text.  Look better for tiny, inven.

         CHAN  ←  GDDCHN(CHAN);		get a DD channel (-1 for any, failure)
		  RDDCHN(CHAN);		release a channel; (-1 for all of them)
		  
		  ERASE(CHAN);	        clear a DD channel (-1 means yours)
		  DPYUP(CHAN,BUFFER(-1));Deposit the buffer on DD channel CHAN;
		  PJUP;			send buffer to MOS display on PDP11
*		  SHOW(CHAN,LIN(-1));	video switch LIN (-1 for yours) to CHAN;
*		  SHOWA(CHAN,LIN(-1));	add CHAN to LIN;
*		  SHOWS(CHAN,LIN(-1));	subtract CHAN from LIN;
		  PPPOS(YLO,YHI);	position page printer between YLO,YHI;

		  XGPUP(SIZE);     send the DD buffer to the XGP, SIZE=-5 to +5
		  XGPQUE(SIZE);    like XGPUP, but creates a new job to do XGPing
*                 DDFONT(X1,Y1,X2,Y2,FONTFIL,CHAR("A"),BASE(0),LKERN(0),RKERN(0));
          		insert DD buffer bounded by X1,Y1,X2,Y2 into font file.
                  DDPAK(I,LBUF,J1,J2); pack scnln I bet. J1,J2 into LBUF 36 bt/wrd

         CHAN  ←  SYNMAP(ORDER);   which channels are the video synthesizer's;
				   ORDER=0 is most significant + or - 1 next, etc.
      SUCCESS  ←  MAPSET(F);       set vid inten table. F(X) is real [0,1]→[0,1]
      SUCCESS  ←  MAPMON(P);	   set v.i.t. to a monotonic function X↑P
      SUCCESS  ←  MAPGRY(P);	   set vit to a gray coded monotonic function X↑P

		  LINSCN(N,MAP,DT,LINENO);	scan channels in MAP at rate DT;
		  MAPSCN(N,MAP,DT,LINENO);	LINSCN, but VDS bit maps in MAP;
		  SCNOFF;			turn off the scanning (in SW mode);
		  SCNFRZ;		     	SCNOFF, but doesn't restore screen;
		  SCNINC(INC);			change the stepsize in the scan;

		  DDSTOR(DDARRAY);	store the buffer in an array;
		  DDLOAD(DDARRAY);	load the buffer from an array;
		  DDOR(DDARRAY);	or an array into the buffer;
		  DDAND(DDARRAY);	and the buffer with an array;
		  DDEXCH(DDARRAY);	exchange an array with the buffer;
		  GETDDF(FILNAME);	load the buffer from a file;
		  PUTDDF(FILNAME);	save the buffer in a file;
		  GETMIT(FILNAME);	load the buffer from a file;
		  PUTMIT(FILNAME);	save the buffer in a file;

 +                FNTSEL(FONT#,"FNTNAME");  define a font #;
*+                FNTPOS(XP,YP,XS(1),YS(1),DXS(0),DYS(0))
         		                    position & transform fonted text
 +                FNTEXT(REAL X,Y; INTEGER F; STRING TXT);  deposit fonted text;
*+                FNTLIN(REAL X1,Y1,X2,Y2; INTEGER THIK(0));
                                            draw line in FNTPOS co-ords;
*+                FNTDOT(REAL X1,Y1; INTEGER THIK(0)); dot in FNTPOS co-ords
 +                FNTREC(REAL X1,Y1,X2,Y2);            rectangle    "
 +                FNTELL(REAL X1,Y1,X2,Y2);            ellipse      "
 +                FNTPOL(INTEGER N; REFERENCE REAL X1,Y1); polygon  "


		  DDSIZ		a constant, the number of words in a DD array;

* Arguments followed by a value in parens default to the bracketed value.

- The absolute physical screen dimension are 512 pixels in X by 481 in Y.
  TEXTD characters are 6 logical pixels in X by 10 in Y, spaces included.

+ Line and dot thickness and the FNT routines are provided for compatibility
  with the device independent routines in GRAHDR.SAI[GOD,HPM]. DDHDR currently
  ignores thickness parameters, and converts all fonted text requests
  into standard size TEXTD characters.
GRAPHICS TUTORIAL

	The following was contributed by Chris Van Wyk.  It describes
the features most users are likely to want or need; in particular, it does not
deal with several ``hacks.''

	First, you should include the statement
REQUIRE "DDHDR[HDR,AAM]" SOURCE_FILE;


at the beginning of your program.  Then the following procedures will be
available for use anywhere in your program.

	DDINIT			This procedure initializes the DD buffer;
				you should call it before you do anything
				else to the DD buffer, or when you want to
				clear it.

	SCREEN (XLO,YLO,XHI,YHI)
				This procedure declares the ``logical''
				dimensions of the whole buffer; that is,
				it declares that future coordinates will
				be given with respect to a Cartesian system
				with lower left corner at (XLO,YLO) and
				upper right corner at (XHI,YHI).

	SCREEM (XLO,YLO,XHI,YHI)
				This procedure returns the values you set
				with your call to SCREEN, in case you forget
				them.

	Commands in the following list affect the DD buffer ONLY.  Nothing will
change on the DD screen as a result of calling these procedures.

	DRKEN			Calling this procedure means that subsequent
				writing to the DD buffer will be ``dark.''

	LITEN			Calling this procedure means that subsequent
				writing to the DD buffer will be ``light.''

	INVEN			Calling this procedure means that subsequent
				writing to the DD buffer will change ``lights''
				to ``darks'' and vice versa.

	DOT (X,Y)		Write a dot in logical position (X,Y).

	LINE (X1,Y1,X2,Y2)	Draw a line from logical position (X1,Y1)
				to (X2,Y2).

	RECTAN (X1,Y1,X2,Y2)	Draw a filled-in rectangle with lower left
				corner at logical position (X1,Y1) and
				upper right corner at (X2,Y2).

	ELLIPS (X1,Y1,X2,Y2)	Inscribe a filled-in ellipse in the rectangle
				with extreme corners at (X1,Y1) and (X2,Y2).

	POLYGO (N,X[1],Y[1])	Draw a filled-in polygon with successive
				vertices at positions (X[1],Y[1]), (X[2],Y[2]),
				..., (X[N],Y[N]).

	Procedures in this group also affect only the DD buffer, but rather
than draw pictures, they place text in the buffer. If you blanch at the prospect
of drawing letters for yourself, become familiar with these friendly fellows.

	TXTPOS (X,Y,XS,YS)	Subsequent TEXT or TEXTD procedure calls should
				place text with lower left corner at (X,Y);
				XS and YS are the height and width of characters:
				to get roughly ``normal'' sized DD characters,
				use
					XS = 6/512 * (XHI - XLO)
					YS = 10/481 * (YHI - YLO).

	TEXT ("STRING")		Write the string argument in the DD buffer
				according to the preceding TXTPOS setting.

	TEXTD ("STRING")	Use dot characters to write the string argument
				to the DD buffer according the the TXTPOS setting;
				this is useful for writing tiny characters or
				when in INVEN mode.

	(Both TEXT and TEXTD keep track of the last place they wrote, so successive
calls to TEXT or TEXTD will write the arguments across the page on the same line,
or begin a new line if the string argument contains a carriage return-line feed.)

	Procedures in this group affect the DD display.

	CHAN ← GDDCHN (N)	Usually, you'll do this with N = -1.  That means
				look for a free DD channel, and grab it and put
				its number into CHAN if there is one; otherwise,
				use the same DD channel you're on for display.

	RDDCHN (CHAN)		Release DD channel number CHAN.

	ERASE (CHAN)		Clear the screen on DD channel number CHAN.

	DPYUP (CHAN)		Display the DD buffer on DD channel CHAN.
				It's a good idea to follow this command with
				an INCHWL, so you can watch what happens.

	SHOW (CHAN)		Switch your display so you can watch what's
				happening on DD channel CHAN.

	SHOWA (CHAN)		Add DD channel CHAN to the one you're already
				looking at; that is, merge the two pictures.

	SHOWS (CHAN)		Subtract DD channel CHAN from the one you're
				looking at; that is, `` get this trash off my
				screen!''

	To preserve your work for posterity, you can get a copy of it on the
XGP; use either of these procedures:

	XGPUP (SIZE)		Hand the DD buffer to the XGP.  Handy SIZEs are
					2	gives one-to-one picture
					5	blows up pic so one page is
						about one screen
					4	like 5, but better if you have
						lots of big dark regions

	XGPQUE (SIZE)		Start a new job to XSPOOL the DD buffer.  Useful
				if XGP is busy.  SIZE is as above.
Here's a sample program using most of the tools described above.

    begin
    require "ddhdr.sai[hdr,aam]" source_file;
    define CRLF = "('15&'12)";

    integer I, CHAN;
    real array X,Y [1:5];

    DDinit;
    CHAN ← Gddchn (-1);
    print ("channel number",CVOS(CHAN));
         comment octal, for compatibility with system keyboard commands;
    Screen (0,0,100,100);
    Erase (CHAN);
    Show (CHAN);

    comment draw a small chessboard in the lower left corner of the screen;
    Liten;
    for I ← 1 step 2 until 7 do
	Rectan (1, I, 9, I + 1);
    Inven;
    for I ← 1 step 2 until 7 do
	Rectan (I, 1, I + 1, 9);
    Dpyup (CHAN); Inchwl;

    comment draw a small Ellipse in the upper right quadrant;
    Liten;
    Ellips (50,50,70,70);
    Inven;
    Txtpos (50,50,1.172,2.083);
    Textd ("Here is an Ellipse"); Textd (" produced with");
    Textd (CRLF&"Ellips (50,50,70,70)");
    Dpyup (CHAN); Inchwl;
	     
    comment draw a larger Ellipse overlapping the other, near the center;
    Ellips (30,50,70,80);
    Txtpos (20,50,1.172,2.083);
    Textd ("Here is an Ellipse");
    Textd (CRLF&"produced with");
    Textd (CRLF&"Ellips (30,50,70,80)");
    Dpyup (CHAN); Inchwl;

    comment draw initials of program author;
    Liten;
    Line (0,100,10,80); Line (10,80,20,100);
    Line (25,100,35,80); Line (35,80,45,90);
    Line (45,90,55,80); Line (55,80,65,100);
    Dpyup (CHAN); Inchwl;

    comment draw a concave Polygon in the lower right corner;
    X[1] ← 70; Y[1] ← 40;
    X[2] ← 60; Y[2] ← 20;
    X[3] ← 70; Y[3] ← 30;
    X[4] ← 95; Y[4] ←  5;
    X[5] ←100; Y[5] ← 50;
    Polygo (5,X[1],Y[1]);
    Dpyup (CHAN); Inchwl;

    Rddchn (CHAN)
    end

 ∂07-Mar-79  0006	HPM  	writing sideways   
TXTPOS has two new parameters and allows you to specify an arbitrary
linear transformation on the text. They have default value 0, which
results in the old meaning.

the new calling sequence is TXTPOS(X,Y,XS,YS,DXS,DYS);

To make normal horizontal text of characters W wide and H high, do

TXTPOS(X,Y, W,H, 0,0) or just  TXTPOS(X,Y, W,H) as before.

To make sideways text lying on its left side, do

TXTPOS(X,Y, 0,0, -H,W)

To make text on its right side (reading downwards), do

TXTPOS(X,Y, 0,0, H,-W)

To make text rotated from the horizontal by an arbitrary angle T, do

TXTPOS(X,Y, W*COS(T),H*COS(T), -H*SIN(T),W*SIN(T));

To make horizontal, italicized, text, do

TXTPOS(X,Y, W,H, 0.5*W, 0);

I leave the other possibilities to you.  Consider XS and YS the main
diagonal of a 2 x 2 matrix that takes a straight, horizontal, prototype
character into the skewed, rotated one actually drawn. DXS and DYS are
the off-diagonal elements of that matrix.


∂29-Jul-79  1516	SL  	TXTPOS Parameterization  
Hans, with regard to the appended message, I note,

    X   W*COS(CCWROT)  H*{[COS(CCWROT)*TAN(CWSLANT)]-SIN(CCWROT)}  x
   ( )=(                                                         )( )
    Y   W*SIN(CCWROT)  H*{[SIN(CCWROT)*TAN(CWSLANT)]+COS(CCWROT)}  y

    X   XS  DXS  x
   ( )=(       )( )
    Y   DYS  YS  y

     XS = W*COS(CCWROT)     DXS = H*{[COS(CCWROT)*TAN(CWSLANT)]-SIN(CCWROT)}
    DYS = W*SIN(CCWROT)      YS = H*{[SIN(CCWROT)*TAN(CWSLANT)]+COS(CCWROT)}

Mightn't it be useful to introduce a parameterization that accepts "corner,
width, height, rot. and slant angles (degrees))":

	TP(X,Y,W,H,CCWROT,CWSLANT)

  -- Sid

[Sure, but somebody had to do the analysis first! Thanks, Sid!
 Actually, one point remains unaddressed, namely that the SCREEN
 co-ordinates may not specify a 1:1 aspect ratio. If you want
 characters to look the same at all angles the aspect ratio
 parameters will have to be thrown into the matrix orthogonally
 to the H, W numbers.]
-----		
GOD routines

        to use:   REQUIRE "GRAHDR[HDR,AAM]" SOURCE_FILE;
	uses:     GRASAI.REL[GOD]

	The graphics routines on [GOD,HPM] are superficially similar to
the ones on [GRA,HPM], but provide an extended device-independent graphics
service. To make a drawing one or more devices (graphics servers) must be
activated to receive graphics commands. Currently there are servers for
Data discs, the XGP and the video synthesizer. (Also a quick kludge for the
Grinnell.)  In addition the graphics
commands can be written into files (called GOD files), which can be
displayed later with system programs called DDJOB, XGPJOB, SYNJOB, and GRNJOB. GOD
files can be called as subroutines in graphics programs.  GOD files can
also be fed to a program called TSTJOB which makes a SAIL program that, if
run, recreates the GOD file given to the TSTJOB. Editing the SAIL program
provides a way of modifying existing GOD files.

	Diagrams in the form of GOD files can be included in documents by
the graphics escape features of XGPSYG.

	The following procedures are provided in addition to the ones in
the GRA package.

JOBID ← DDJOB;		   create a server that draws on Data Disc displays

JOBID ← XGPJOB;            create a graphics server that will output on the XGP

JOBID ← SYNJOB(HIG(480),WID(512),BIT(9))  make a server that produces gray
			   scale renditions a drawing

JOBID ← FILJOB("FILNAME"); make a graphics server that writes graphics commands
			   into a GOD file;

JOBID ← TSTJOB;		   create a server that prints graphics commands as
			   a SAIL program

JOBID ← QUASH(JOBID);      temporarily deafen a server. It still exists, but
			   will not act on subsequent display commands.

JOBID ← INCITE(JOBID);	   reactivate a server. Undoes the effect of QUASH.

JOBID ← KILJOB(INTEGER JOBID);  kill a server. Closes the file opened by a
			   FILJOB, simply expunges all other server types.

JOBID ← DETJOB(JOBID,GRAFILE); detach a server, but give it a graphics file
		           to process first. Server is lost to main program.

	GRAFIL(GRAFILE);    tell currently active servers to begin
			    processing a graphics file. Afterwards
			    they will be ready to listen to main
			    program again.

	FNTSEL(FONT#,FNTNAME);  select a font, and give it a number (0-127)

	FNTPOS(XP,YP,XS(1),YS(1),DXS(0),DYS(0)); position a font pixel grid
		            at XP, YP in SCREEN co-ordinates, with 
			    transfromation set by other four parameters.
			    1, 1, 0, 0 results in undistorted characters.

	FNTEXT(X,Y,FONT#,TEXT); deposit TEXT in the indicated font with
			    lower left corner offset (X,Y) font pixels
			    (as distorted by FNTPOS parameters) from
			    the last FNTPOS position.

	FNTLIN(X1,Y1,X2,Y2; INTEGER THIK(0)); draw a line between pixel
			    co-ordinates indicated, in grid defined by
			    last FNTPOS.

	FNTDOT(X1,Y1,THIK(0)); a dot in FNTPOS co-ordinates.

	FNTREC(X1,Y1,X2,Y2); a FNTPOS rectangle.

	FNTELL(X1,Y1,X2,Y2); a FNTPOS ellipse.

	FNTPOL(N,X[1:N],Y[1:N]); a FNTPOS polygon.

	PICFIL(X1,Y1,X2,Y2,PICFILE); insert a picture in the rectangle
			     bounded in X by X1 and X2 and by Y1 and Y2 in Y.
			     On gray scale servers this picture will come out
			     shaded. On binary devices a halftone is produced.
			     PICFILE should be in hand/eye format.

	PICFIT(X1,Y1,X2,Y2; STRING FILE); insert a transposed picture in the
			     indicated rectangle.

BUFSIZ← DDSIZ(INTEGER JOBID(-1)); return the display buffer size
		                  of the indicated server.
TYPHDR routines

        to use:   REQUIRE "TYPHDR.SAI[GOD,HPM]" SOURCE_FILE;

	The TYPHDR routines extend the GRAHDR package to permit
reasonably convenient two dimensional typesetting of text in mixed
fonts, for inclusion in GOD diagrams. The central concept
is of a box of a certain size containing a two dimensional assembly of text
and graphics. Such a box has an origin, which may be plopped
down at a given place in diagram. Some of the commands create
new boxes out of text, some by gluing together other ones, and
some change the size or the origin of a box.

	The following procedures are provided:

	FNTSELECT(FONT#,FONTNAME);	use this instead of FNTSEL in the GRAHDR

BOX  ←  JTXT(FONT#,TEXT);     return a box containing TEXT in the indicated font

BOX  ←  JCAT(A,B);	      horizontally combine a number of boxes. Origin
     thru		      ends up on left edge of resulting box. Useful
BOX  ←  JCAT6(A,B,C,D,E,F);   for stringing together different fonts.

BOX  ←  JTAC(A,B);	      horizontally combine boxes, but leave origin
     thru		      on the right end.
BOX  ←  JTAC7(A,B,C,D,E,F,G); 

BOX  ←  JBEL(A,B);	      vertically stack text boxes. Useful for
     thru		      assembling multiple lines of text.
BOX  ←  JBEL7(A,B,C,D,E,F,G); 

BOX  ←  JSUB(A,B);	      make new box that is box A subscripted by box B

BOX  ←  JEXP(A,B);            make box with A superscripted by B

BOX  ←  JXBP(A,B,C);	      make box with A sub B super C

BOX  ←  PADD(DX1,DY1,DX2,DY2; A);  padd box A on all four sides (margins)

BOX  ←  SHIF(DX1,DY1; A);     shift origin of box A

BOX  ←  JUL(A);		      make new box with contents of A underlined

BOX  ←  JSQR(A);	      make a square root sign around A

BOX  ←  JDIV(A,B);	      center A above B and put a division bar between

BOX  ←  XCENTER(A);	      center the origin of box A in X

BOX  ←  YCENTER(A);	      center A in Y

BOX  ←  CENTER(A);	      move origin of A to its center in X and Y

BOX  ←  RIGHTIFY(A);	      move origin to right of A

BOX  ←  LEFTIFY(A);	      move origin to left of A

BOX  ←  TOPIFY(A);	      move origin to top of A

BOX  ←  BOTTOMIFY(A);	      move origin to bottom of A

        DEPOSIT(X,Y; A);      deposit box A into the diagram such that its
			      origin is X (FNTPOS distorted) pixels to the
			      right and Y pixels above the text position
			      specified by the last FNTPOS.